package it.webrules.deploymanager.core.condition;

import it.webrules.deploymanager.core.config.ConfigurationException;
import it.webrules.xsd.dmc.config.v1.CompareMode;
import it.webrules.xsd.dmc.config.v1.Condition;
import it.webrules.xsd.dmc.config.v1.ConditionOn;
import it.webrules.xsd.dmc.config.v1.RangeCondition;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class ConditionEngine {

	protected final Logger logger = LoggerFactory.getLogger(this.getClass());

	protected abstract Object getMBeanValue(Condition condition) throws Exception;

	public boolean elabCondition(Condition condition) throws Exception {

		Object value = null;
		ConditionOn type = condition.getType();

		switch (type) {
		case MBEAN:
			value = getMBeanValue(condition);
			break;
		default:
			throw new ConfigurationException("Only MBEAN as condition type is supported!");
		}

		if (value == null)
			return false;

		CompareMode compareas = condition.getCompareas();

		if (condition.getEquals() != null) {
			Integer result = compareOperation(condition.getEquals(), value, compareas);
			if (result != null && result == 0)
				return true;
		}

		if (condition.getNotequals() != null) {
			Integer result = compareOperation(condition.getNotequals(), value, compareas);
			if (result != null && result != 0)
				return true;
		}

		if (condition.getLessthan() != null) {
			Integer result = compareOperation(condition.getLessthan(), value, compareas);
			if (result != null && result > 0)
				return true;
		}

		if (condition.getMorethan() != null) {
			Integer result = compareOperation(condition.getMorethan(), value, compareas);
			if (result != null && result < 0)
				return true;
		}

		if (condition.getRange() != null) {
			RangeCondition range = condition.getRange();
			Integer lowerbound = compareOperation(range.getMin(), value, compareas);
			Integer upperbound = compareOperation(range.getMax(), value, compareas);

			if (lowerbound != null && upperbound != null && lowerbound <= 0 && upperbound >= 0)
				return true;

		}

		return false;

	}

	private Integer compareOperation(Object a, Object b, CompareMode compareas) {

		if (compareas.equals(CompareMode.STRING)) {

			return String.valueOf(a).compareTo(String.valueOf(b));

		} else {
			// CompareMode.NUMBER

			try {
				return Double.compare(Double.parseDouble(String.valueOf(a)), Double.parseDouble(String.valueOf(b)));
			} catch (NumberFormatException e) {
				logger.error("Variable not numeric! '{}' or '{}'.", a, b);
				return null;
			}
		}

	}

}
